﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockFinder.Model;
using StockFinder.Indicators.Day.ClosePrice;
using StockFinder.Indicators.Day.Volume;

namespace StockFinder.Scenarios
{
    public class Scenario1
    {
        /*
         *  Volume >= 200%
         *  Price change >= 4%
         *  Drawdown of 3*ATR
         */

        public void Run(Symbol symbol)
        {
            if (symbol.Prices == null || symbol.Prices.Count == 0)
            {

            }

            const decimal VOLUME_MULTIPLIER = 2;
            const decimal PRICE_CHANGE_MULTIPLIER = 1.04m;
            const decimal ATR_MULTIPLIER = 3;

            var volumeIndicator = SimpleMovingAverageDailyVolumeDayIndicator.Month;
            var atrIndicator = ExponentialMovingAverageTrueRangeClosePriceDayIndicator._14;

            volumeIndicator.ApplyIndicator(symbol.Prices);
            atrIndicator.ApplyIndicator(symbol.Prices);

            var indiciatorLookback = Math.Max(volumeIndicator.LookbackPeriod, atrIndicator.LookbackPeriod) - 1;

            var priceCount = symbol.Prices.Count;
            var pricesArray = symbol.Prices.OrderBy(p => p.PriceDate).ToArray();

            var openNewPosition = false;
            Trade trade = null;
            var trades = new List<Trade>();
            decimal highPriceOfTrade = 0;

            #region System loop

            //loop prices
            for (var i = 0; i < priceCount; i++)
            {
                #region Indicator history check

                //need enough indicator history
                if (i < indiciatorLookback) continue;

                #endregion

                #region Daily variables
                //var samplePrices = pricesArray.Take(i).ToList();                
                var todayPrice      = pricesArray[i];
                var yesterdayPrice = pricesArray[i - 1];
                #endregion

                #region Premarket checks

                //close a position if we have broken stop loss level
                if (trade != null)
                {
                    if (yesterdayPrice.AdjustedClose <= trade.TrailingStopLoss)
                    {
                        trade.ExitDate = todayPrice.PriceDate;
                        trade.ExitPrice = todayPrice.AdjustedOpen;

                        highPriceOfTrade = 0;
                        trade = null;
                    }
                }

                //adjust trailing stop loss only upwards when new price high of trade reached
                if (trade != null)
                {
                    //adjust when highest price of trade reached and in position
                    if (yesterdayPrice.AdjustedClose > highPriceOfTrade)
                    {
                        highPriceOfTrade = yesterdayPrice.AdjustedClose;

                        var yesterdayAtr = yesterdayPrice.DayIndicators[atrIndicator.IndicatorName];
                        var stopLoss = yesterdayPrice.AdjustedClose - (yesterdayAtr * ATR_MULTIPLIER);

                        //only adjust trailing stop loss upwards
                        if (stopLoss > trade.TrailingStopLoss)
                        {
                            trade.TrailingStopLoss = stopLoss;
                        }
                    }
                }                

                //open new position due to yesterday action?
                if (openNewPosition)
                {
                    openNewPosition = false;

                    //make sure we arent already in a position
                    if (trade == null)
                    {
                        var priceBoughtAt = todayPrice.AdjustedOpen;
                        var yesterdayAtr = yesterdayPrice.DayIndicators[atrIndicator.IndicatorName];
                        var stopLoss = priceBoughtAt - (yesterdayAtr * ATR_MULTIPLIER);
                        
                        trade = new Trade();
                        trades.Add(trade);
                        trade.EntryDate = todayPrice.PriceDate;
                        trade.EntryPrice = priceBoughtAt;
                        trade.HardStopLoss = stopLoss;
                        trade.TrailingStopLoss = stopLoss;

                        highPriceOfTrade = trade.EntryPrice;
                    }
                }

                #endregion

                #region After market checks

                //1 is the volume today >= 200% than average?
                var closeVolume = todayPrice.Volume;                
                var averageVolume = todayPrice.DayIndicators[SimpleMovingAverageDailyVolumeDayIndicator.Month.IndicatorName];

                if (closeVolume > 0 && averageVolume > 0)
                {
                    var thresholdVolume = averageVolume * VOLUME_MULTIPLIER;

                    if (closeVolume >= thresholdVolume)
                    {
                        //2 price change of 4%+?
                        var closePrice = todayPrice.AdjustedClose;
                        var yesterdayClosePrice = yesterdayPrice.AdjustedClose;

                        if (closePrice > 0 && yesterdayClosePrice > 0)
                        {
                            var thresholdPriceChange = yesterdayClosePrice * PRICE_CHANGE_MULTIPLIER;

                            if (closePrice >= thresholdPriceChange)
                            {
                                //3 passed filter
                                openNewPosition = true;
                            }
                        }
                    }
                }

                #endregion
            }

            #endregion
        }
    }
}
